/**
 * Captain
 * © 2017 Captain copyright，All rights reserved.
 * http://www.sccaptain.com.cn
 * 
 * JAVA : 8
 * 文  件  名: ZipCompressor.java
 * 创  建  人: liutao(liu.tao@sccaptain.com.cn)
 * 创建时间: 2017年7月20日 上午9:48:59
 * 版         本: 1.0.0
 * 备         注:
 * 修订历史:
 */
package com.material.c2c.web.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.springframework.util.StringUtils;

/**
 * 文件压缩。
 * 
 * @since 1.0
 * @version 1.0
 * @author liutao(liu.tao@sccaptain.com.cn)
 */
public class ZipCompressor {

  static final int BUFFER = 8192;
  private File zipFile;

  public ZipCompressor(String pathName) {
    zipFile = new File(pathName);
  }

  /**
   * 多文件压缩。
   * 
   * @param String...
   *          pathName
   * @since 1.0
   * @version 1.0
   * @author liutao(liu.tao@sccaptain.com.cn)
   */
  public void compress(String... pathName) {
    FileOutputStream fileOutputStream = null;
    CheckedOutputStream cos = null;
    ZipOutputStream out = null;
    try {
      fileOutputStream = new FileOutputStream(zipFile);
      cos = new CheckedOutputStream(fileOutputStream, new CRC32());
      out = new ZipOutputStream(cos);
      String basedir = "";
      for (int i = 0; i < pathName.length; i++) {
        compress(new File(pathName[i]), out, basedir);
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (!StringUtils.isEmpty(out)) {
        try {
          out.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
      if (!StringUtils.isEmpty(cos)) {
        try {
          cos.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
      if (!StringUtils.isEmpty(fileOutputStream)) {
        try {
          fileOutputStream.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    }
  }

  /**
   * 单文件/单文件夹压缩。
   * 
   * @param srcPathName
   * @since 1.0
   * @version 1.0
   * @author liutao(liu.tao@sccaptain.com.cn)
   */
  public void compress(String srcPathName) {
    File file = new File(srcPathName);
    if (!file.exists())
      throw new RuntimeException(srcPathName + "不存在！");
    FileOutputStream fileOutputStream = null;
    CheckedOutputStream cos = null;
    ZipOutputStream out = null;
    try {
      fileOutputStream = new FileOutputStream(zipFile);
      cos = new CheckedOutputStream(fileOutputStream, new CRC32());
      out = new ZipOutputStream(cos);
      String basedir = "";
      compress(file, out, basedir);
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (!StringUtils.isEmpty(out)) {
        try {
          out.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
      if (!StringUtils.isEmpty(cos)) {
        try {
          cos.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
      if (!StringUtils.isEmpty(fileOutputStream)) {
        try {
          fileOutputStream.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    }
  }

  /**
   * 
   * @param file
   * @param out
   * @param basedir
   * @since 1.0
   * @version 1.0
   * @author liutao(liu.tao@sccaptain.com.cn)
   */
  private void compress(File file, ZipOutputStream out, String basedir) {
    // 判断是目录还是文件
    if (file.isDirectory()) {
      this.compressDirectory(file, out, basedir);
    } else {
      this.compressFile(file, out, basedir);
    }
  }

  /**
   * 压缩一个目录。
   * 
   * @param dir
   * @param out
   * @param basedir
   * @since 1.0
   * @version 1.0
   * @author liutao(liu.tao@sccaptain.com.cn)
   */
  private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
    if (!dir.exists())
      return;
    File[] files = dir.listFiles();
    for (int i = 0; i < files.length; i++) {
      // 递归
      compress(files[i], out, basedir + dir.getName() + "/");
    }
  }

  /**
   * 压缩一个文件。
   * 
   * @param file
   *          压缩文件
   * @param out
   *          zip流
   * @param basedir
   * @since 1.0
   * @version 1.0
   * @author liutao(liu.tao@sccaptain.com.cn)
   */
  private void compressFile(File file, ZipOutputStream out, String basedir) {
    if (!file.exists()) {
      return;
    }
    BufferedInputStream bis = null;
    try {
      bis = new BufferedInputStream(new FileInputStream(file));
      ZipEntry entry = new ZipEntry(basedir + file.getName());
      out.putNextEntry(entry);
      int count;
      byte data[] = new byte[BUFFER];
      while ((count = bis.read(data, 0, BUFFER)) != -1) {
        out.write(data, 0, count);
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (!StringUtils.isEmpty(bis)) {
        try {
          bis.close();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    }
  }

  public static void main(String[] args) {
    ZipCompressor zip = new ZipCompressor("E:\\you\\测试2.zip");
    zip.compress("E:\\qin\\wangzhi.txt");
  }
}
